×
☰ See All Chapters

Exception handling using Spring @ControllerAdvice Annotation

Major drawback we had from @ExceptionHander annotation is we need Separate exception handler methods in every controller class and this may result in code duplication.  Solution we have for this drawback is @ControllerAdvice annotation. Exception handler methods from @ControllerAdvice annotated class will handle all exceptions from all controller classes. We do not need to have separate exception handler methods in each controller classes.

Inside ControllerAdvice class you can declare any number of exception handler methods each for handling specific exception or you can declare one exception handler method accepting Global Exception class. In the below class we have declared two exception handler methods. First method handles Exception, second method handles ArrayIndexOutOfBoundsException. If there are any ArrayIndexOutOfBoundsException then it will be handled by second method and if there are any NullPointerException then as there is no specific handler methods for NullPointerException, it will be handled from first method.

package com.java4coding;

 

import org.springframework.web.bind.annotation.ControllerAdvice;

import org.springframework.web.bind.annotation.ExceptionHandler;

import org.springframework.web.bind.annotation.ResponseBody;

 

@ControllerAdvice

@ResponseBody

public class ControllerAdvisor {

       

        @ExceptionHandler()

        public String handleException(Exception ex) {

                return "Exception caught in ControllerAdvisor | " + " Exception Type: " + ex.getClass().getName();

        }

       

        @ExceptionHandler()

        public String handleException(ArrayIndexOutOfBoundsException ex) {

                return "Exception caught in ControllerAdvisor | " + " Exception Type: ArrayIndexOutOfBoundsException";

        }

}

 

If you like to return the same response from exception handler methods of ControllerAdvice class as the response from controller class you have to annotate the ControllerAdvice class with @ResponseBody annotation. If it is not annotated with @ResponseBody annotation then it is just handling exception.

Example for @ ControllerAdvice annotation

pom.xml

<project xmlns="https://maven.apache.org/POM/4.0.0"

        xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"

        xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">

        <modelVersion>4.0.0</modelVersion>

        <groupId>com.java4coding</groupId>

        <artifactId>ControllerAdvice_WithSpringBoot</artifactId>

        <packaging>war</packaging>

        <version>0.0.1-SNAPSHOT</version>

        <name>ControllerAdvice_WithSpringBoot</name>

        <parent>

                <groupId>org.springframework.boot</groupId>

                <artifactId>spring-boot-starter-parent</artifactId>

                <version>1.5.6.RELEASE</version>

        </parent>

        <dependencies>

                <dependency>

                        <groupId>org.springframework.boot</groupId>

                        <artifactId>spring-boot-starter-web</artifactId>

                </dependency>

                <dependency>

                        <groupId>org.apache.tomcat.embed</groupId>

                        <artifactId>tomcat-embed-jasper</artifactId>

                        <scope>provided</scope>

                </dependency>

                <dependency>

                        <groupId>org.springframework.boot</groupId>

                        <artifactId>spring-boot-devtools</artifactId>

                        <optional>true</optional>

                </dependency>

        </dependencies>

        <properties>

                <java.version>1.8</java.version>

        </properties>

</project>

DemoController1.java

package com.java4coding;

 

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RequestMethod;

import org.springframework.web.bind.annotation.RestController;

 

@RestController

public class DemoController1 {

        @RequestMapping(value = "/demo1/not-exist", method = RequestMethod.GET, headers = "Accept=*/*")

        public String oneFaultyMethod() {

                if (true) {

                        throw new ArrayIndexOutOfBoundsException("Demo error message");

                }

                return null;

        }

}

DemoController2.java

package com.java4coding;

 

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RequestMethod;

import org.springframework.web.bind.annotation.RestController;

 

@RestController

public class DemoController2 {

        @RequestMapping(value = "/demo2/not-exist", method = RequestMethod.GET, headers = "Accept=*/*")

        public String oneFaultyMethod() {

                if (true) {

                        throw new NullPointerException("Demo error message");

                }

                return null;

        }

}

ControllerAdvisor.java

package com.java4coding;

 

import org.springframework.web.bind.annotation.ControllerAdvice;

import org.springframework.web.bind.annotation.ExceptionHandler;

import org.springframework.web.bind.annotation.ResponseBody;

 

@ControllerAdvice

@ResponseBody

public class ControllerAdvisor {

       

        @ExceptionHandler()

        public String handleException(Exception ex) {

                return "Exception caught in ControllerAdvisor.handleException | " + " Exception Type: " + ex.getClass().getName();

        }

       

        @ExceptionHandler()

        public String handleArrayIndexOutOfBoundsException(ArrayIndexOutOfBoundsException ex) {

                return "Exception caught in ControllerAdvisor.handleArrayIndexOutOfBoundsException | " + " Exception Type: ArrayIndexOutOfBoundsException";

        }

       

}

SpringBootDemo.java

package com.java4coding;

 

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

 

@SpringBootApplication

public class SpringBootDemo {

        public static void main(String[] args) {

                SpringApplication.run(SpringBootDemo.class, args);

        }

}

application.properties

# Applicationn context name

server.contextPath=/ControllerAdviceExample

Project Directory Structure

spring-controlleradvice-annotation-0
 

Output

spring-controlleradvice-annotation-1
 
spring-controlleradvice-annotation-2
 

All Chapters
Author